#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <syslog.h>

#include "frcomm.h"
#include "frmem.h"
#include "frlist.h"
#include "frhash2.h"

static Frhash_header st_hash_test;

/*******************************************************************************
*  FUNC     :  节点内存释放
*  ARGS     :  p_st_node  (Frlist_node *)
*  RTN      :
*  NOTE     :  注意需要在ct->lock下操作
*******************************************************************************/
static void __hash_node_free(Frlist_node *p_st_node)
{
    if(p_st_node==NULL || p_st_node->data == NULL)
        return;
    frfree(p_st_node->data);
    return;
}

/*******************************************************************************
*  FUNC     :  节点内容出力
*  ARGS     :  p_st_node       (Frlist_node *)
            :  p_outbuff       (出力内容指针)
            :  ui_buff_size    (出力内容空间)
*  RTN      :  比较一致返回0，其他返回1
*  NOTE     :
*******************************************************************************/
static void __hash_node_show(Frlist_node* p_st_node, char *p_outbuff, unsigned int ui_buff_size)
{
    if(p_st_node == NULL || ui_buff_size <= 0 )
        return;

    snprintf(p_outbuff, ui_buff_size, "data=[%s]\n", (char *)p_st_node->data);
    return;
}

/*******************************************************************************
*  FUNC     :  查找函数
*  ARGS     :  p_st_node       (Frlist_node *)
            :  p_compare_data  (比较用数据)
*  RTN      :  比较一致返回0，其他返回1
*  NOTE     :
*******************************************************************************/
static int __hash_node_find(Frlist_node *p_st_node, const void *p_compare_data)
{
    if(p_st_node==NULL || p_st_node->data == NULL || p_compare_data == NULL)
        return 1;
    
    return strcmp((char *)p_compare_data, p_st_node->data);
}

void test_hashstr(void)
{
    int i_loop=0, i_outbuff_size =102400;
    Frlist_header *p_st_list_hdr=NULL; 
    Frlist_node *p_st_node=NULL;
    char *p_value=NULL, *p_outbuff=NULL, arr_buff[20];
    char *p_key = "a01";
    
    if(frhash2_create(&st_hash_test, 1000) != FR_SUCC)
    {
        printf("frhash_create fail\n");
        return ;
    }
    
    //增加节点
    p_st_node = frlist_node_create(frstrdup("data a01"));
    frhash2_addStr(&st_hash_test, p_key, strlen(p_key), p_st_node);
    
    for(i_loop=0; i_loop < 20; i_loop++)
    {
        snprintf(arr_buff, sizeof(arr_buff), "test%d", i_loop);
        p_st_node = frlist_node_create(frstrdup(arr_buff));
        if(p_st_node)
        {
            frhash2_addStr(&st_hash_test, arr_buff, strlen(arr_buff), p_st_node);
        }
    }
    
    //循环出力
    //i_loop循环用变量; p_hash_hdr hash表指针; p_st_lst_hdr链表用临时变量
    printf("========================================LOOP START\n");
    FRHASH_LOOP(i_loop,&st_hash_test, p_st_list_hdr)
    {
        p_st_node = FRLIST_FIRST_NODE(p_st_list_hdr);
        while(p_st_node)
        {
            printf("key=%s value=[%s]\n", p_st_node->p_key, (char *)FRLIST_GET_NODE_DATA(p_st_node) );
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
        }
    }
    printf("========================================LOOP END\n");
    
    //出力hash数据
    p_outbuff = frmalloc(i_outbuff_size);
    if(p_outbuff)
    {
        *p_outbuff = '\0';
        frhash2_show(&st_hash_test, p_outbuff, i_outbuff_size, __hash_node_show);
        printf("output hash data\n%s\n\n", p_outbuff);
        
        frfree(p_outbuff);
    }
   
    //使用回调函数查询
    p_value = "test0";
    p_st_node = frhash2_find(&st_hash_test, p_value, __hash_node_find);
    if(p_st_node)
        printf("frhash2_find:find data in hash(%s)\n", p_value);
    else
        printf("frhash2_find:not find data in hash(%s)\n", p_value);

    //查询，删除
    p_key = "a01";
    p_st_node = frhash2_getStr(&st_hash_test, p_key, strlen(p_key) );
    if(p_st_node)
    {
        printf("frhash2_getStr:find data in hash(key=%s value=[%s])\n", p_key, (char *)FRLIST_GET_NODE_DATA(p_st_node));
        frhash2_del(&st_hash_test, p_st_node, __hash_node_free);
        printf("frhash2_del:delete node in hash(key=%s)\n", p_key);
    }
    else
        printf("frhash2_getStr:not find data in hash(key=%s)\n", p_key);

    //出力hash数据
    p_outbuff = frmalloc(i_outbuff_size);
    if(p_outbuff)
    {
        *p_outbuff = '\0';
        frhash2_show(&st_hash_test, p_outbuff, i_outbuff_size, __hash_node_show);
        printf("output hash data\n%s\n\n", p_outbuff);
        
        frfree(p_outbuff);
    }
    
    //释放该hash
    frhash2_free(&st_hash_test, __hash_node_free);
    
    return;
}


void test_hashLong(void)
{
    int i_loop=0, i_outbuff_size =102400;
    Frlist_header *p_st_list_hdr=NULL;
    Frlist_node *p_st_node=NULL;
    char *p_outbuff=NULL, arr_buff[20];
    long l_key=0L;
    
    if(frhash2_create(&st_hash_test, 10000) != FR_SUCC)
    {
        printf("frhash_create fail\n");
        return ;
    }
    
    //增加节点
    for(i_loop=0; i_loop < 10; i_loop++)
    {
        snprintf(arr_buff, sizeof(arr_buff), "test%d", i_loop);
        p_st_node = frlist_node_create(frstrdup(arr_buff));
        if(p_st_node)
        {
            frhash2_addLong(&st_hash_test, i_loop, p_st_node);
        }
    }

    //循环出力
    //i_loop循环用变量; p_hash_hdr hash表指针; p_st_lst_hdr链表用临时变量
    printf("========================================LOOP START\n");
    FRHASH_LOOP(i_loop,&st_hash_test, p_st_list_hdr)
    {
        p_st_node = FRLIST_FIRST_NODE(p_st_list_hdr);
        while(p_st_node)
        {
            printf("key=%ld value=[%s]\n", p_st_node->l_key, (char *)FRLIST_GET_NODE_DATA(p_st_node) );
            p_st_node = FRLIST_NEXT_NODE(p_st_node);
        }
    }
    printf("========================================LOOP END\n");

    //出力hash数据
    p_outbuff = frmalloc(i_outbuff_size);
    if(p_outbuff)
    {
        *p_outbuff = '\0';
        frhash2_show(&st_hash_test, p_outbuff, i_outbuff_size, __hash_node_show);
        printf("output hash data\n%s\n\n", p_outbuff);
        
        frfree(p_outbuff);
    }

    //查询，删除
    for(i_loop=0; i_loop < 4; i_loop++)
    {
        l_key = i_loop;
        p_st_node = frhash2_getLong(&st_hash_test, l_key );
        if(p_st_node)
        {
            printf("find data in hash(%ld) data=[%s]\n", l_key, (char *)FRLIST_GET_NODE_DATA(p_st_node));
            
            frhash2_del(&st_hash_test, p_st_node, __hash_node_free);
            printf("delete node in hash(%ld)\n", l_key);
        }
        else
            printf("not find data in hash(%ld)\n", l_key);
    }

    //出力hash数据
    p_outbuff = frmalloc(i_outbuff_size);
    if(p_outbuff)
    {
        *p_outbuff = '\0';
        frhash2_show(&st_hash_test, p_outbuff, i_outbuff_size, __hash_node_show);
        printf("output hash data\n%s\n\n", p_outbuff);
        
        frfree(p_outbuff);
    }
    
    //释放该hash
    frhash2_free(&st_hash_test, __hash_node_free);
    
    return;
}

int main(int argc, char *argv[])
{
    frmem_init();
    
    test_hashstr();
    //test_hashLong();
    
    frshow_leak();
    frmem_destroy();
    return 0;
}
